package net_app.tcp_sms;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;

/**
 * 开发Socket网络编程入门代码的服务器端,实现接收消息
 */
public class ServerDemo1 {

    // 使用静态变量存储一个线程池对象
    private static ExecutorService pool = new ThreadPoolExecutor(3,5,6, TimeUnit.SECONDS,
            new ArrayBlockingQueue<>(2),Executors.defaultThreadFactory(),
            new ThreadPoolExecutor.AbortPolicy());

    // 定义一个静态的List集合存储当前全部在线的socket管道
    public static List<Socket> allOnlineSocket = new ArrayList<>();

    public static void main(String[] args) {
        try {
            System.out.println("==========服务端启动成功========");
            // 1.注册端口
            ServerSocket serverSocket = new ServerSocket(7777);
            // 定义一个死循环由主线程负责不断的接收客户端的socket管道连接
            while (true) {
                // 2.每接收到一个客户端的Socket管道,交给一个独立的子线程负责读消息
                Socket socket = serverSocket.accept();
                System.out.println(socket.getRemoteSocketAddress() + "上线了");
                allOnlineSocket.add(socket);// 上线完成
                // 任务对象负责读取消息
                pool.execute(new ServerReaderRunnable(socket));
            }

        } catch (IOException e) {
            e.getStackTrace();
        }
    }
    public static class ServerReaderRunnable extends Thread {
        private Socket socket;
        public ServerReaderRunnable(Socket socket){
            this.socket = socket;
        }
        @Override
        public void run() {
            try {
                // 3.从socket通信管道中得到一个字节输入流
                InputStream is = socket.getInputStream();
                // 4.把字节输入流包装成缓冲字符输入流进行消息的接收
                BufferedReader br = new BufferedReader(new InputStreamReader(is));
                // 5.按照行读取消息
                String msg;
                while ((msg = br.readLine()) != null){
                    System.out.println(socket.getRemoteSocketAddress() + "说了:" + msg);
                    // 把这个消息进行端口转发给全部客户端socket管道
                    sendMsgToAll(msg);
                }
            } catch (IOException e) {
                System.out.println(socket.getRemoteSocketAddress() + "下线了");
                ServerDemo1.allOnlineSocket.remove(socket);
            }
        }

        private void sendMsgToAll(String msg) throws IOException {
            for (Socket socket : ServerDemo1.allOnlineSocket) {
                PrintStream ps = new PrintStream(socket.getOutputStream());
                ps.println(msg);
                ps.flush();
            }
        }
    }
}
